/*
 * @Author: xiaosihan
 * @Date: 2024-09-23 21:07:06
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2025-01-28 04:01:58
 */

/*
 * @Author: xiaosihan
 * @Date: 2023-05-09 00:35:17
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2023-05-09 02:33:28
 */

import {
  Camera,
  Color,
  DepthFormat,
  DepthTexture,
  LinearFilter,
  NoBlending,
  Object3D,
  RGBAFormat,
  Scene,
  ShaderChunk,
  ShaderMaterial,
  UnsignedShortType,
  Vector2,
  WebGLRenderTarget,
  WebGLRenderer,
} from "three";
import copyShader from "../shaders/copyShader";
import FullScreenQuad from "./fsQuad";
import fsQuad from "./fsQuad";

// 选中对象的深度纹理
const selectDepthTexture = (() => {
  const baseDepthTexture = new DepthTexture(1024, 1024);
  baseDepthTexture.format = DepthFormat;
  baseDepthTexture.type = UnsignedShortType;
  baseDepthTexture.anisotropy = 16;
  return baseDepthTexture;
})();

// 选中对象的纹理
const selectTextureTarget = new WebGLRenderTarget(512, 512, {
  minFilter: LinearFilter,
  magFilter: LinearFilter,
  format: RGBAFormat,
  depthTexture: selectDepthTexture,
  anisotropy: 16,
});

// 深度测试后的选中纹理
const selectDethpTestTextureTarget = new WebGLRenderTarget(512, 512, {
  minFilter: LinearFilter,
  magFilter: LinearFilter,
  format: RGBAFormat,
  anisotropy: 16,
});

const blur1TextureTarget = new WebGLRenderTarget(512, 512, {
  minFilter: LinearFilter,
  magFilter: LinearFilter,
  format: RGBAFormat,
});

const size = new Vector2();

//深度比对纹理
const depthTestShader = new ShaderMaterial({
  uniforms: {
    color: { value: new Color("#440000") }, //颜色
    opacity: { value: 1 }, // 透明度
    depthTest: { value: true }, // 开启深度测试
    baseDepth: { value: null }, // 整个场景的深度纹理
    selectDepth: { value: null }, // 选中的对象深度纹理
  },
  vertexShader: `
        ${ShaderChunk.common}
        ${ShaderChunk.logdepthbuf_pars_vertex}
        varying vec2 vUv;
        void main() {
            vUv = uv;
            // gl_Position = vec4(position, 1.0);
            // gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position, 1.0);
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            ${ShaderChunk.logdepthbuf_vertex}
        }
    `,
  fragmentShader: `
        ${ShaderChunk.logdepthbuf_pars_fragment}
        uniform vec3 color;
        uniform float opacity;
        uniform bool depthTest;
        uniform sampler2D baseDepth;
        uniform sampler2D selectDepth;
        varying vec2 vUv;
        void main() {
            if( depthTest ){
                if(texture2D(baseDepth, vUv).r + 0.0001 < texture2D(selectDepth, vUv).r){
                    discard;
                }
                if(texture2D(baseDepth, vUv).r == 1.0){
                    discard;
                }
                gl_FragColor = vec4(color, opacity);
            }else{
               if(texture2D(selectDepth, vUv).r < 1.0){
                    gl_FragColor = vec4(color, opacity);
               }else{
                   discard;
               }
            }

            ${ShaderChunk.logdepthbuf_fragment}
        }
    `,
  depthTest: true,
  depthWrite: true,
  transparent: true,
});

// 场景对象
const scene = new Scene();

// 给模型覆盖一层颜色 后处理通道
export default function cover_pass(
  renderer: WebGLRenderer,
  camera: Camera,
  object3d: Object3D,
  baseDepthTexture: DepthTexture,
  devicePixelRatio: number
) {
  const {
    cover_enable = false,
    cover_color = "#04fa12",
    cover_opacity = 1,
    cover_depth_test = true, // 颜色叠加是否开启深度测试
  } = object3d.userData;

  if (!cover_enable || cover_opacity === 0) {
    return;
  }

  // 保存原帧缓冲区
  const originRenderTarget = renderer.getRenderTarget();

  // 设置选中目标的帧缓冲区
  renderer.getSize(size);
  size.multiplyScalar(devicePixelRatio);
  selectTextureTarget.setSize(size.x, size.y);
  selectDethpTestTextureTarget.setSize(size.x, size.y);
  blur1TextureTarget.setSize(size.x, size.y);

  renderer.setRenderTarget(selectTextureTarget);
  scene.children = [object3d];
  renderer.clear();
  renderer.render(scene, camera);

  //更具深度测试绘制叠加颜色
  renderer.setRenderTarget(originRenderTarget);
  renderer.clearDepth();
  depthTestShader.uniforms.color.value.set(cover_color);
  depthTestShader.uniforms.opacity.value = cover_opacity;
  depthTestShader.uniforms.depthTest.value = cover_depth_test;
  depthTestShader.uniforms.baseDepth.value = baseDepthTexture;
  depthTestShader.uniforms.selectDepth.value = selectDepthTexture;
  fsQuad.render(renderer, depthTestShader);

  // 调试代码
  // renderer.setRenderTarget(null);
  // renderer.clearDepth();
  // copyShader.uniforms.map.value = blur2TextureTarget.texture;
  // fsQuad.render(renderer, copyShader);
  // return;
}
